﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Timers;
using YourPersonalTrainer.DataAccessLayer;
using YourPersonalTrainer.BusinessLayer.Interfaces;

namespace YourPersonalTrainer.BusinessLayer
{
    public delegate void WorkoutUpdateHandler(object sender, string currentItemName, int secondsRemaining);

    [XmlRoot("workout")]
    public class Workout : List<WorkoutItem>
    {
        private Vocaliser m_Vocaliser = new Vocaliser();
        private bool m_Stopped = false;
        private IWorkoutTimer m_Timer;
        private int m_CurrentWorkoutItemIndex;
        private DateTime m_LastItemStartTime;

        public event WorkoutUpdateHandler UpdateHandler;
        public Action<string> PlayAudioHandler;

        public TimeSpan ElapsedTime;

        public IWorkoutTimer Timer
        {
            set
            {
                m_Timer = value;
            }
        }

        public Workout(IWorkoutTimer workoutTimer)
        {
            m_Timer = workoutTimer;
        }

        public Workout()
        {
        }



        public void Start()
        {
            m_CurrentWorkoutItemIndex = 0;
            m_Stopped = false;
            m_Timer.Elapsed = TimerElapsed;
            StartCurrentWorkoutItem();
            ProcessCurrentWorkoutItem(DateTime.Now);
            m_Timer.Start();
        }

        public void Skip()
        {
            m_CurrentWorkoutItemIndex++;
            StartCurrentWorkoutItem();
            ProcessCurrentWorkoutItem(DateTime.Now);
        }

        public void StartCurrentWorkoutItem()
        {
            if (CurrentWorkoutItem != null)
            {
                Thread thread = new Thread(SayWorkoutItemName);

                thread.Start();

                if (File.Exists(CurrentWorkoutItem.AudioFileLocation))
                {
                    if (PlayAudioHandler != null)
                    {
                        PlayAudioHandler(CurrentWorkoutItem.AudioFileLocation);
                    }
                }

                m_LastItemStartTime = DateTime.Now;
            }
        }

        public void SayWorkoutItemName()
        {
            m_Vocaliser.Say(CurrentWorkoutItem.Name);
        }

        public WorkoutItem CurrentWorkoutItem
        {
            get
            {
                if (m_CurrentWorkoutItemIndex < Count)
                {
                    return this[m_CurrentWorkoutItemIndex];
                }
                else
                {
                    return null;
                }
            }
        }

        private void TimerElapsed()
        {
            ProcessCurrentWorkoutItem(DateTime.Now);
        }

        private void ProcessCurrentWorkoutItem(DateTime currentTime)
        {
            if (CurrentWorkoutItem != null)
            {
                ElapsedTime = currentTime - m_LastItemStartTime;
                int secondsRemaining = CurrentWorkoutItem.DurationInSeconds - (int)ElapsedTime.TotalSeconds;
                if (secondsRemaining <= 0)
                {
                    if (m_CurrentWorkoutItemIndex < Count - 1)
                    {
                        m_CurrentWorkoutItemIndex++;
                        if (UpdateHandler != null)
                        {
                            UpdateHandler(this, CurrentWorkoutItem.Name, CurrentWorkoutItem.DurationInSeconds);
                        }
                        StartCurrentWorkoutItem();
                    }
                    else
                    {
                        Stop();
                        m_Vocaliser.Say("All Done");
                    }
                }
                else
                {
                    if (UpdateHandler != null)
                    {
                        UpdateHandler(this, CurrentWorkoutItem.Name, secondsRemaining);
                    }
                }
            }
        }

        public TimeSpan Duration()
        {
            int durationInSeconds = this.Sum(workoutItem => workoutItem.DurationInSeconds);

            return new TimeSpan(0, 0, durationInSeconds);
        }

        public void SaveToFile(string fileName)
        {
            System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(this.GetType());
            TextWriter w = new StreamWriter(fileName);
            x.Serialize(w, this);
            w.Close();
        }

        public void Pause()
        {
            if (m_Stopped)
            {
                m_Timer.Start();
                m_Stopped = false;
            }
            else
            {
                Stop();
            }
        }

        public void Stop()
        {
            if (m_Timer != null)
            {
                m_Timer.Stop();
            }
            m_Stopped = true;
        }
    }

}
